package main

import (
	"fmt"
	"sync"
)

type SafeDict2 struct {
	data          map[string]int
	*sync.RWMutex // sync.Mutex API 也有点不一样
}

func NewSafeDict2(data map[string]int) *SafeDict2 {
	return &SafeDict2{data, &sync.RWMutex{}}
}

func (d *SafeDict2) Len() int {
	d.RLock()
	defer d.RUnlock()
	return len(d.data)
}

func (d *SafeDict2) Put(key string, value int) (int, bool) {
	d.Lock()
	defer d.Unlock()
	old_value, ok := d.data[key]
	d.data[key] = value
	return old_value, ok
}

func (d *SafeDict2) Get(key string) (int, bool) {
	d.RLock()
	defer d.RUnlock()
	old_value, ok := d.data[key]
	return old_value, ok
}

func (d *SafeDict2) Delete(key string) (int, bool) {
	d.Lock()
	defer d.Unlock()
	old_value, ok := d.data[key]
	if ok {
		delete(d.data, key)
	}
	return old_value, ok
}

func write2(d *SafeDict2) {
	d.Put("banana", 5)
}

func read2(d *SafeDict2) {
	fmt.Println(d.Get("banana"))
}

func main() {
	d := NewSafeDict2(map[string]int{
		"apple": 2,
		"pear":  3,
	})
	go read2(d)
	write2(d)

	fmt.Println(d)
}